<?php
/**
 * 抽象工厂
 *
 * 之前的工厂方法 ,每个具体工厂只能创建一个 对应实例
 *
 * 抽象工厂可以 , 每个具体工厂可以创建一系列 实例
 *
 * 具体工厂提供一系列的创建接口 ,
 * */

/**
 * 再看抽象工厂
 *
 *      抽象工厂提供了创建一系列相关对象的接口, 而无需指定他们具体的类
 *
 *      1. 将对象的创建交给工厂 , 减少客户端非必要职责
 *      2. 一个工厂可以提供一系列相关的对象 , 可以一次修改所有对象都将改变 , 牵一发而动全身
 *      3. 大批量对象的替换
 * */

abstract class Product{
    protected $name = '抽象产品';

    /**
     * @return string
     */
    public function getName()
    {
        echo $this->name.PHP_EOL;
    }
}

abstract class ProductA extends Product {
    protected $name = '抽象产品A';
}

abstract class ProductB extends Product{
    protected $name = '抽象产品B';
}

class ContractProductARed extends ProductA{
    protected $name = '真实产品A - 红色系列';
}
class ContractProductAYellow extends ProductA{
    protected $name = '真实产品A - 黄色系列';
}

class ContractProductBRed extends ProductB{
    protected $name = '真实产品B - 红色系列';
}
class ContractProductBYellow extends ProductB{
    protected $name = '真实产品B - 黄色系列';
}

/**
 * 抽象工厂
 * */
abstract class AbstractFactory{
    abstract public function getProductA();
    abstract public function getProductB();
}

/**
 * 红色工厂生产红色产品
 * */
class FactoryRed extends AbstractFactory{

    public function getProductA()
    {
        return new ContractProductARed();
    }

    public function getProductB()
    {
        return new ContractProductBRed();
    }
}
/**
 * 黄色工厂生产黄色工厂产品
 * */
class FactoryYellow extends AbstractFactory{

    public function getProductA()
    {
        return new ContractProductAYellow();
    }

    public function getProductB()
    {
        return new ContractProductBYellow();
    }
}
// 这一步从配置读取
$factory = new FactoryRed();

$productA = $factory->getProductA();
$productB = $factory->getProductB();

$productA->getName();
$productB->getName();
